// Copyright (c) 2025 Yao Yu
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at https://mozilla.org/MPL/2.0/.

use rand::{rngs::StdRng, RngCore};
use ostd::sync::SpinLock;
use spin::Once;

static RNG: Once<SpinLock<StdRng>> = Once::new();

pub fn getrandom(dst: &mut [u8]) {
    // Ok(RNG.get().unwrap().lock().try_fill_bytes(dst)?)
    RNG.get().unwrap().lock().fill_bytes(dst)
}
pub fn randu32() -> u32 {
    RNG.get().unwrap().lock().next_u32()
}

// 随机数生成器初始化
pub fn init() {
    use rand::SeedableRng;
    use ostd::arch::read_random;
    let mut seed = <StdRng as SeedableRng>::Seed::default();
    let mut chunks = seed.as_mut().chunks_exact_mut(size_of::<u64>());
            for chunk in chunks.by_ref() {
                let src = read_random().expect("read_random failed multiple times").to_ne_bytes();
                chunk.copy_from_slice(&src);
            }
            let tail = chunks.into_remainder();
            let n = tail.len();
            if n > 0 {
                let src = read_random().expect("read_random failed multiple times").to_ne_bytes();
                tail.copy_from_slice(&src[..n]);
            }
    RNG.call_once(|| SpinLock::new(StdRng::from_seed(seed)));
}